/*
 *  Property Mapper, simple automatic GUI generator for JavaBeans using annotations.
 *  Copyright (C) 2008 Jon Lennersten, Johan Hedin
 *
 *  This file is part of Property Mapper.
 *
 *  Property Mapper is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Property Mapper is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Property Mapper.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.mawell.common.propertymapperswing;

import com.toedter.calendar.JDateChooser;
import com.mawell.common.propertymapper.*;
import org.apache.log4j.Logger;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

public class PropertyView extends JPanel {

    private static int INT_COL_NUMS = 8;
    private static int STRING_COL_NUMS = 15;

    private static Logger logger = Logger.getLogger(PropertyView.class);

    private PropertySettingController parentController;
    private JFrame parentFrame;
    private Translation trans;
    private String header;

    private Object theObject;

    private PropertyConfigurationContainer pContainer;
    private PropertyMapper pMapper;

    private JPanel inputPanel;

    private JButton saveButton;

    private Map<MapPropertyConfiguration, JMapTable> maps;

    private Dimension MIN_WINDOW_SIZE = new Dimension(20, 20);

    public PropertyView(PropertySettingController c, Object theObject, JFrame parent, Translation trans, String header) {
        parentFrame = parent;
        parentController = c;
        this.theObject = theObject;
        this.trans = trans;
        this.header = header;
        init();
    }


    public PropertyView(PropertySettingController c, Object theObject, JFrame parent, Translation trans) {
        this(c, theObject, parent, trans, trans.getLabelHeader());
    }

    public PropertyView(PropertySettingController c, Object theObject, JFrame parent, String header) {
        this(c, theObject, parent, new TranslationImpl(), header);
    }
    
    public PropertyView(PropertySettingController c, Object theObject, JFrame parent) {
        this(c, theObject, parent, new TranslationImpl());
    }


    /**
     * Initialize the GUI.
     *
     */
    public void init() {
        logger.debug("Initializing property GUI");

        maps = new HashMap<MapPropertyConfiguration, JMapTable>();

        this.setLayout(new GridBagLayout());

        //Generate all input fields
        inputPanel = new JPanel(new GridBagLayout());
        inputPanel.setBorder(new EmptyBorder(4, 4, 4, 4));

        pMapper = new PropertyMapper();
        pMapper.setDescription(trans);
        pContainer = pMapper.getConfiguration(theObject);

        createFieldsFor(pContainer, inputPanel);

        JPanel flexiPanel = new JPanel(new GridBagLayout());
        flexiPanel.setBorder(new EmptyBorder(0, 0, 0, 0));

        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 1.0; // add horizontal space to this component
        c.weighty = 1.0; // add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; // end of row
        c.gridheight = GridBagConstraints.REMAINDER; // end of column
        c.fill = GridBagConstraints.BOTH; // do not fill vertically and horizontally if bigger than expected

        inputPanel.add(flexiPanel, c);


        saveButton = new JButton(trans.getLabelSave());
        saveButton.setEnabled(false);
        ActionListener lst = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                for(MapPropertyConfiguration mapPropertyConfiguration : maps.keySet()) {
                    mapPropertyConfiguration.setValue(maps.get(mapPropertyConfiguration).getMap());
                }

                if(pContainer.isSet()) {
                    pMapper.setProperties(pContainer, theObject);
                    parentController.propertySavePressed(theObject);
                    saveButton.setEnabled(false);
                } else {
                    String message = trans.getLabelMandatoryFieldMissing();
                    JOptionPane.showMessageDialog(parentFrame, message, trans.getLabelInformation(), JOptionPane.ERROR_MESSAGE);
                }
            }
        };

        saveButton.addActionListener(lst);

        logger.debug("Adding components");

        JPanel enablePanel = new JPanel();
        JPanel contentPanel = new JPanel(new GridBagLayout());
        contentPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
        JPanel buttonPanel = new JPanel();

        c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 1; // add horizontal space to this component
        c.weighty = 1; // add vertical space to this component
        c.gridwidth = 1;
        c.gridheight = 1;
        c.fill = GridBagConstraints.BOTH; // fill vertically and horizontally if bigger than expected

        JScrollPane scroller = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scroller.setMinimumSize(MIN_WINDOW_SIZE);

        scroller.getViewport().add(inputPanel);

/*
        JScrollPane scroller = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
               JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        scroller.getViewport().add(inputPanel);
*/
        contentPanel.add(scroller, c);

        buttonPanel.add(saveButton);

        if(header != null) {
        JLabel headerLabel = new JLabel(header);
        headerLabel.setFont(new Font("Arial", Font.BOLD, 18));
        headerLabel.setForeground(new Color(51, 51, 51));

        c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; // end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected

        add(headerLabel, c);
        }

        c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; // end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected
        add(enablePanel, c);

        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0.1; // do not add horizontal space to this component
        c.weighty = 0.1; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; // end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.BOTH; // do not fill vertically and horizontally if bigger than expected
        add(contentPanel, c);

        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; // end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected
        add(buttonPanel, c);
    }

    private void createFieldsFor(PropertyConfigurationContainer pContainer, JComponent comp) {
        for(PropertyConfiguration pConfig : pContainer.getPropertyConfigurations()) {

            if(pConfig instanceof BooleanPropertyConfiguration) {
                addBoolean((BooleanPropertyConfiguration)pConfig, comp);
            } else if(pConfig instanceof DatePropertyConfiguration) {
                addDate((DatePropertyConfiguration)pConfig, comp);
            } else if(pConfig instanceof IntPropertyConfiguration) {
                addInt((IntPropertyConfiguration)pConfig, comp);
            } else if(pConfig instanceof StringPropertyConfiguration) {
                addString((StringPropertyConfiguration)pConfig, comp);
            } else if(pConfig instanceof MapPropertyConfiguration) {
                addMap((MapPropertyConfiguration)pConfig, comp);
            } else if(pConfig instanceof EnumPropertyConfiguration) {
                addEnum((EnumPropertyConfiguration)pConfig, comp);
            } else if(pConfig instanceof PropertyConfigurationContainer) {
                addContainer((PropertyConfigurationContainer)pConfig, comp);
            }
        }
    }

    private void addContainer(final PropertyConfigurationContainer pContainer, JComponent comp) {
        JPanel child = new JPanel(new GridBagLayout());
        TitledBorder border = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray), pContainer.getProperty());
        child.setBorder(border);
        createFieldsFor(pContainer, child);
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; //end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected
        comp.add(child, c);
    }

    private void addBoolean(final BooleanPropertyConfiguration booleanPropertyConfiguration, JComponent comp) {
        if(logger.isDebugEnabled()) {
            logger.debug("Creating GUI for boolean " + booleanPropertyConfiguration.getProperty());
        }

        addLabel(booleanPropertyConfiguration.getDescription(), booleanPropertyConfiguration.isMandatory(), comp);

        final JCheckBox checkBox = new JCheckBox();
        if(booleanPropertyConfiguration.isValue()) {
            checkBox.setSelected(true);
        } else {
            checkBox.setSelected(false);
        }

        checkBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                saveButton.setEnabled(true);
                booleanPropertyConfiguration.setValue(checkBox.isSelected());
            }
        });

        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; //end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected

        comp.add(checkBox, c);
    }

    private void addDate(final DatePropertyConfiguration datePropertyConfiguration, JComponent comp) {
        if(logger.isDebugEnabled()) {
            logger.debug("Creating GUI for date " + datePropertyConfiguration.getProperty());
        }
        addLabel(datePropertyConfiguration.getDescription(), datePropertyConfiguration.isMandatory(), comp);


        final JDateChooser dateChooser = new JDateChooser(datePropertyConfiguration.getValue());
        String[] transPart = trans.getLocale().split("_");
        dateChooser.setLocale(new Locale(transPart[0], transPart[1]));

        dateChooser.addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                if(evt.getPropertyName().equals("date")) {
                    saveButton.setEnabled(true);
                    datePropertyConfiguration.setValue(dateChooser.getDate());
                }
            }
        });

        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; //end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected

        comp.add(dateChooser, c);
    }

    private void addInt(final IntPropertyConfiguration intPropertyConfiguration, JComponent comp) {
        if(logger.isDebugEnabled()) {
            logger.debug("Creating GUI for int " + intPropertyConfiguration.getProperty());
        }

        addLabel(intPropertyConfiguration.getDescription(), intPropertyConfiguration.isMandatory(), comp);
        final IntField intField = new IntField(String.valueOf(intPropertyConfiguration.getValue()), INT_COL_NUMS);

        intField.getDocument().addDocumentListener(new DocumentListener() {

            public void insertUpdate(DocumentEvent e) {
                if(e.getDocument().getLength() > 0) {
                    saveButton.setEnabled(true);
                    intPropertyConfiguration.setValue(Integer.parseInt(intField.getText()));
                } else {
                    saveButton.setEnabled(false);
                }
            }

            public void removeUpdate(DocumentEvent e) {
                if(e.getDocument().getLength() > 0) {
                    saveButton.setEnabled(true);
                    intPropertyConfiguration.setValue(Integer.parseInt(intField.getText()));
                } else {
                    saveButton.setEnabled(false);
                }
            }

            public void changedUpdate(DocumentEvent e) {
            }
        });

        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; //end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected

        comp.add(intField, c);
    }

    private void addString(final StringPropertyConfiguration stringPropertyConfiguration, JComponent comp) {
        if(logger.isDebugEnabled()) {
            logger.debug("Creating GUI for string " + stringPropertyConfiguration.getProperty());
        }

        addLabel(stringPropertyConfiguration.getDescription(), stringPropertyConfiguration.isMandatory(), comp);

        if(stringPropertyConfiguration.getPossibleValues() == null &&
                stringPropertyConfiguration.getValueEntity() == null) {
            final JTextField textField = new JTextField(stringPropertyConfiguration.getValue(), STRING_COL_NUMS);

            textField.getDocument().addDocumentListener(new DocumentListener() {
                public void insertUpdate(DocumentEvent e) {
                    saveButton.setEnabled(true);
                    stringPropertyConfiguration.setValue(textField.getText());
                }

                public void removeUpdate(DocumentEvent e) {
                    saveButton.setEnabled(true);
                    stringPropertyConfiguration.setValue(textField.getText());
                }

                public void changedUpdate(DocumentEvent e) {
                }
            });

            GridBagConstraints c = new GridBagConstraints();
            c.anchor = GridBagConstraints.NORTHWEST;
            c.weightx = 0; // do not add horizontal space to this component
            c.weighty = 0; // do not add vertical space to this component
            c.gridwidth = GridBagConstraints.REMAINDER; //end of row
            c.gridheight = 1;
            c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected

            comp.add(textField, c);
        } else {
            final JComboBox stringComboBox;
            if(stringPropertyConfiguration.getValueEntity() != null) {
                //Create the drop down box by getting all possible values from controller
                stringComboBox = new JComboBox();

                if(!stringPropertyConfiguration.isMandatory()) {
                    //Not mandatory, add an empty item
                    stringComboBox.addItem(new IDItem("", ""));
                }

                Map valueEntites = parentController.getEntityMap(
                        stringPropertyConfiguration.getValueEntity(),
                        stringPropertyConfiguration.getValueNameField());

                Set<String> values = valueEntites.keySet();
                IDItem id;

                for(String value : values) {
                    id = new IDItem(value, (String)valueEntites.get(value));
                    stringComboBox.addItem(id);
                    if(value.equals(stringPropertyConfiguration.getValue())) {
                        stringComboBox.setSelectedItem(id);
                    }
                }
            } else {
                stringComboBox = new JComboBox(stringPropertyConfiguration.getPossibleValues());
                if(stringPropertyConfiguration.getValue() != null) {
                    stringComboBox.setSelectedItem(stringPropertyConfiguration.getValue());
                }
            }

            //set the selected value. If set from stringPropertyConfiguration it will be the same, otherwise
            //the first item will be set.
            if(stringComboBox.getSelectedItem() != null) {
                if(stringPropertyConfiguration.getValueEntity() != null) {
                    stringPropertyConfiguration.setValue(((IDItem)stringComboBox.getSelectedItem()).id);
                } else {
                    stringPropertyConfiguration.setValue((String)stringComboBox.getSelectedItem());
                }
            }

            stringComboBox.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    saveButton.setEnabled(true);
                    if(stringPropertyConfiguration.getValueEntity() != null) {
                        stringPropertyConfiguration.setValue(((IDItem)stringComboBox.getSelectedItem()).id);
                    } else {
                        stringPropertyConfiguration.setValue((String)stringComboBox.getSelectedItem());
                    }
                }
            });
            GridBagConstraints c = new GridBagConstraints();
            c.anchor = GridBagConstraints.NORTHWEST;
            c.weightx = 0; // do not add horizontal space to this component
            c.weighty = 0; // do not add vertical space to this component
            c.gridwidth = GridBagConstraints.REMAINDER; //end of row
            c.gridheight = 1;
            c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected

            comp.add(stringComboBox, c);
        }
    }


    private void addMap(final MapPropertyConfiguration mapPropertyConfiguration, JComponent comp) {
        if(logger.isDebugEnabled()) {
            logger.debug("Creating GUI for map " + mapPropertyConfiguration.getProperty());
        }

        addLabel(mapPropertyConfiguration.getDescription(), mapPropertyConfiguration.isMandatory(), comp);

        final JMapTable mapTable = new JMapTable(trans.getLabelMapKey(), trans.getLabelMapValue());

        maps.put(mapPropertyConfiguration, mapTable);

        Map keyEntities, valueEntites;
        Map<String, IDItem> keyMap = new HashMap<String, IDItem>();
        Map<String, IDItem> valueMap = new HashMap<String, IDItem>();
        IDItem id;


        if(mapPropertyConfiguration.getKeyEntity() != null) {
            //Create the drop down box by getting all entities from controller

            JComboBox comboBox = new JComboBox();
            comboBox.addItem(new IDItem("", ""));

            keyEntities = parentController.getEntityMap(
                    mapPropertyConfiguration.getKeyEntity(),
                    mapPropertyConfiguration.getKeyNameField());

            Set<String> keys = keyEntities.keySet();


            for(String key : keys) {
                id = new IDItem(key, (String)keyEntities.get(key));
                keyMap.put(key, id);
                comboBox.addItem(id);
            }

            mapTable.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(comboBox));
        } else if(mapPropertyConfiguration.getKeyEnumClass() != null) {
            //Create the drop down box by getting all possible values from enum
            try {
                Class eClass = Class.forName(mapPropertyConfiguration.getKeyEnumClass());
                Object[] constants = eClass.getEnumConstants();

                JComboBox enumComboBox = new JComboBox();

                enumComboBox.addItem(null);
                for(Object constant : constants) {
                    enumComboBox.addItem(constant);
                }

                mapTable.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(enumComboBox));

            } catch(ClassNotFoundException e) {
                logger.error("Couldn't create enum drop down list", e);
            }
        }

        if(mapPropertyConfiguration.getValueEntity() != null) {
            //Create the drop down box by getting all entities from controller

            JComboBox comboBox = new JComboBox();
            comboBox.addItem(new IDItem("", ""));

            valueEntites = parentController.getEntityMap(
                    mapPropertyConfiguration.getValueEntity(),
                    mapPropertyConfiguration.getValueNameField());

            Set<String> values = valueEntites.keySet();

            for(String value : values) {
                id = new IDItem(value, (String)valueEntites.get(value));
                valueMap.put(value, id);
                comboBox.addItem(id);
            }

            mapTable.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(comboBox));
        } else if(mapPropertyConfiguration.getValueEnumClass() != null) {
            //Create the drop down box by getting all possible values from enum
            try {
                Class eClass = Class.forName(mapPropertyConfiguration.getValueEnumClass());
                Object[] constants = eClass.getEnumConstants();

                JComboBox enumComboBox = new JComboBox();

                enumComboBox.addItem(null);
                for(Object constant : constants) {
                    enumComboBox.addItem(constant);
                }

                mapTable.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(enumComboBox));

            } catch(ClassNotFoundException e) {
                logger.error("Couldn't create enum drop down list", e);
            }
        }

        Map map = mapPropertyConfiguration.getValue();
        Set keys = map.keySet();

        Object k, v;
        for(Object key : keys) {
            k = ((mapPropertyConfiguration.getKeyEntity() != null) ?
                    keyMap.get(key) : key);

            v = ((mapPropertyConfiguration.getValueEntity() != null) ?
                    valueMap.get(map.get(key)) : map.get(key));

            mapTable.put(k, v);
        }

        mapTable.getModel().addTableModelListener(new TableModelListener() {

            public void tableChanged(TableModelEvent e) {
                saveButton.setEnabled(true);
            }
        });

        JScrollPane scrollPane = new JScrollPane(mapTable);
        mapTable.setPreferredScrollableViewportSize(new Dimension(400, 70));

        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; //end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected

        comp.add(scrollPane, c);
    }

    private void addEnum(final EnumPropertyConfiguration enumPropertyConfiguration, JComponent comp) {
        if(logger.isDebugEnabled()) {
            logger.debug("Creating GUI for enum " + enumPropertyConfiguration.getProperty());
        }

        addLabel(enumPropertyConfiguration.getDescription(), enumPropertyConfiguration.isMandatory(), comp);

        final JComboBox enumComboBox;

        Class eClass = enumPropertyConfiguration.getEnumClass();
        Object[] constants = eClass.getEnumConstants();

        enumComboBox = new JComboBox(constants);
        if(enumPropertyConfiguration.getValue() != null) {
            for(Object o : constants) {
                if(o.toString().equals(enumPropertyConfiguration.getValue().toString())) {
                    enumComboBox.setSelectedItem(o);
                }
            }
        }

        enumComboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                saveButton.setEnabled(true);
                enumPropertyConfiguration.setValue((Enum)enumComboBox.getSelectedItem());
            }
        });
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = GridBagConstraints.REMAINDER; //end of row
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected

        comp.add(enumComboBox, c);
    }

    private void addLabel(String labelText, boolean mandatory, JComponent comp) {
        JLabel label = new JLabel((mandatory ? "* " : "") + labelText + ":");
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weightx = 0; // do not add horizontal space to this component
        c.weighty = 0; // do not add vertical space to this component
        c.gridwidth = 1;
        c.gridheight = 1;
        c.fill = GridBagConstraints.NONE; // do not fill vertically and horizontally if bigger than expected
        comp.add(label, c);
    }
}